package redis

import (
	"errors"
	"github.com/go-redis/redis"
	"math"
	"strconv"
	"time"
)

const (
	oneWeekInSecond = 7 * 26 * 60 * 60
	socrePerVote    = 432 //每一张票所占分数
)

var (
	ErrVoteTimeExpire = errors.New("超出投票时间")
	ErrVoteRepeat     = errors.New("不允许重复投票")
)

func CreatePost(postID, communityID int64) error {
	//将下面两个操作合并为事务操作
	pipeline := client.TxPipeline()

	//帖子时间
	pipeline.ZAdd(GetRedisKey(KeyPostTimeZSet), redis.Z{
		Score:  float64(time.Now().Unix()),
		Member: postID,
	})

	//帖子分数
	pipeline.ZAdd(GetRedisKey(KeyPostScoreZSet), redis.Z{
		Score:  float64(time.Now().Unix()),
		Member: postID,
	})

	//把帖子id加到社区set中
	cKey := GetRedisKey(KeyCommunitySetPF + strconv.Itoa(int(communityID)))
	pipeline.SAdd(cKey, postID)
	_, err := pipeline.Exec()
	return err
}

func VoteForPost(userID, postID string, value float64) error {
	postTime := client.ZScore(GetRedisKey(KeyPostTimeZSet), postID).Val()
	if float64(time.Now().Unix())-postTime > oneWeekInSecond {
		return ErrVoteTimeExpire
	}

	//查询投票记录
	ov := client.ZScore(GetRedisKey(KeyPostVotedZSetPrefix+postID), userID).Val()
	diff := math.Abs(ov - value) //计算两次投票的差值
	if value == ov {
		return ErrVoteRepeat
	}
	//如果现在的投票方向大于原来的方向就是加分
	var op float64
	if value > ov {
		op = 1
	} else {
		op = -1
	}

	//下面的记录数据和更新分数都要进行事务操作
	pipeline := client.Pipeline()
	//根据dir更新分数
	pipeline.ZIncrBy(GetRedisKey(KeyPostScoreZSet), socrePerVote*diff*op, postID)

	//记录用户为帖子投票的数据
	if value == 0 {
		pipeline.ZRem(GetRedisKey(KeyPostVotedZSetPrefix+postID), postID)
	} else {
		pipeline.ZAdd(GetRedisKey(KeyPostVotedZSetPrefix+postID), redis.Z{
			Score:  value,
			Member: userID,
		})
	}

	_, err := pipeline.Exec()
	return err
}
